////////////////////////////////////////////////////////////////////////////////
// Copyright 2010 Michael Schmalle - Teoti Graphix, LLC
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
// http://www.apache.org/licenses/LICENSE-2.0 
// 
// Unless required by applicable law or agreed to in writing, software 
// distributed under the License is distributed on an "AS IS" BASIS, 
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and 
// limitations under the License
// 
// Author: Michael Schmalle, Principal Architect
// mschmalle at teotigraphix dot com
////////////////////////////////////////////////////////////////////////////////

package fxplugins.registry.restricted
{

import fxplugins.registry.IExtension;
import fxplugins.registry.IExtensionDescriptor;
import fxplugins.registry.IExtensionPoint;
import fxplugins.registry.IExtensionRegistry;

/**
 * Reads an <code>IExtension</code>'s children and converts them to
 * objects of the subclassing reader class.
 * 
 * <p>This reader class implements the Template Method pattern to read
 * extensions and it's child extension descriptors recursivly.</p>
 * 
 * @author Michael Schmalle
 * @copyright Teoti Graphix, LLC
 * @productversion 1.0
 */
public class RegistryReader
{
	//--------------------------------------------------------------------------
	//
	//  Constructor
	//
	//--------------------------------------------------------------------------
	
	/**
	 * Constructor.
	 */
	public function RegistryReader()
	{
	}
	
	//--------------------------------------------------------------------------
	//
	//  Protected :: Methods
	//
	//--------------------------------------------------------------------------
	
	/**
	 * Reads an <code>IExtensionDescriptor</code> descriptor.
	 * 
	 * <p>This method should return <code>true</code> if the attribute is
	 * recongnized by the reader and <code>false</code> if the attribute
	 * is not recognized.</p>
	 * 
	 * @param element The <code>IExtensionDescriptor</code> descriptor to read.
	 * @return A Boolean indicating whether the attribute is valid.
	 */
	protected function readElement(element:IExtensionDescriptor):Boolean
	{
		return false;
	}
	
	/**
	 * Reads an <code>IExtensionDescriptor</code> descriptor's children.
	 * 
	 * @param element The <code>IExtensionDescriptor</code> descriptor to read
	 * is't children using <code>IExtensionDescriptor.getChildren()</code>.
	 */
	protected function readElementChildren(element:IExtensionDescriptor):void
	{
		readElements(element.getChildren(null));
	}
	
	/**
	 * Reads the Array of <code>IExtensionDescriptor</code> descriptors,
	 * calling <code>readElement()</code> on each element.
	 * 
	 * <p>If the <code>readElement()</code> method returns <code>false</code>
	 * on the read, <code>logUnknownElement()</code> will be called on the 
	 * element.</p>
	 * 
	 * @param elements An Array of <code>IExtensionDescriptor</code> descriptors
	 * to read.
	 */
	protected function readElements(elements:Array):void
	{
		var len:int = elements.length;
		for (var i:int = 0; i < len; i++)
		{
			var e:IExtensionDescriptor = elements[i];
			if (!readElement(e))
			{
				logUnknownElement(e);
			}
		}
	}
	
	/**
	 * Logs an element that is not known to the reader implementation.
	 * 
	 * @param element The <code>IExtensionDescriptor</code> descriptor
	 * that was not recognized.
	 */
	protected function logUnknownElement(element:IExtensionDescriptor):void
	{
		trace("logUnknownElement()", element.name);
	}
	
	/**
	 * Reads an entire <code>IExtension</code> element's descriptor
	 * children.
	 * 
	 * @param extension The <code>IExtension</code> element to read it's
	 * <code>IExtensionDescriptor</code> children.
	 */
	protected function readExtension(extension:IExtension):void
	{
		readElements(extension.getExtensionDescriptors());
	}
	
	//--------------------------------------------------------------------------
	//
	//  Public :: Methods
	//
	//--------------------------------------------------------------------------
	
	/**
	 * Reads the <code>IExtensionRegistry</code> using the plugin id and
	 * an extension point it.
	 * 
	 * @param registry The <code>IExtensionRegistry</code> to read from.
	 * @param pluginID The plugin id to retrieve the extension point from
	 * (<code>org.example.acme</code>).
	 * @param extensionPoint The extension point id to retrieve the extension point 
	 * from (<code>org.example.acme.views</code>).
	 */
	public function readRegistry(registry:IExtensionRegistry, 
								 pluginID:String, 
								 extensionPoint:String):void
	{
		var point:IExtensionPoint = registry.getExtensionPoint(
			pluginID, extensionPoint) as IExtensionPoint;
		
		if (point == null)
			return;
		
		var extensions:Array = point.getExtensions();
		var len:int = extensions.length;
		for (var i:int = 0; i < len; i++)
		{
			readExtension(extensions[i]);
		}		
	}
	
	//--------------------------------------------------------------------------
	//
	//  Public Class :: Methods
	//
	//--------------------------------------------------------------------------
	
	/**
	 * Returns an <code>IExtensionDescriptor</code> description.
	 * 
	 * @param The <code>IExtensionDescriptor</code> to read the description.
	 */
	public static function getDescription(element:IExtensionDescriptor):String
	{
		var children:Array = element.getChildren("description");
		if (children.length >= 1)
			return children[0].getValue();
		return "";
	}
	
	/**
	 * @private
	 */
	public static function getClassValue(element:IExtensionDescriptor, 
										 classAttributeName:String):String
	{
		var className:String = element.getAttribute(classAttributeName);
		if (className != null)
			return className;
		
		var children:Array = element.getChildren(classAttributeName)
		if (children.length == 0)
			return null;
		
		return children[0].getAttribute("class");
	}
}
}